package mvc.spring.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

//import mvc.IModel;
import mvc.mainPage.MainModel;
import mvc.mainPage.MainModelCreator;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import utils.UsersOnlineHttpSessionAttributeListener;
import domain.Message;
import domain.Room;
import domain.User;

import DAO.IMessageDAO;
import DAO.IRoomDAO;
import DAO.IUserDAO;

@Controller
public class MainController {

	private static Logger log = Logger.getLogger(MainController.class);

	@Autowired
	private IMessageDAO messageDao;

	@Autowired
	private IRoomDAO roomDao;

	@Autowired
	private IUserDAO userDao;

	@RequestMapping("/logoff")
	public String logoff(HttpServletRequest request) {
		
		request.getSession().invalidate();
		log.debug("logoff action redirect to main");
		return "redirect:/main";
	}
	
	
	@RequestMapping("/changeRoom")
	public String changeRoom(HttpServletRequest request) {
		
		HttpSession session = request.getSession();
		String newRoomId = request.getParameter("roomId");
		
		if (newRoomId != null && !newRoomId.isEmpty()) {
			session.setAttribute("currentRoomId", newRoomId);
		}
		log.debug("changeRoom action redirect to main");						
		return "redirect:/main";
	}
	
	@RequestMapping("/postMessage")
	public String postMessage(HttpServletRequest request) {
		
		String msg = request.getParameter("Message");
		log.debug("incoming msg : " + msg);
		MainModelCreator modelCreator = new MainModelCreator();
		MainModel mainModel = (MainModel) modelCreator.createModel(request);
		
		if (msg != null && !msg.isEmpty() && 
				mainModel.getCurrentRoomId() != null && 
				mainModel.getCurrentUserId() != null) {
			
			User currentUser = userDao.getUser(mainModel.getCurrentUserId());
			Room currentRoom = roomDao.SelectRoom(mainModel.getCurrentRoomId());
			
			Message message = new Message();
			message.setMsg(msg);
			message.setCreateDate(new Date());
			message.setRoom(currentRoom);
			message.setUser(currentUser);
			
			messageDao.createMessage(message);
		}
		log.debug("postMessage action redirect to main");						
		return "redirect:/main";
	}
	
	@RequestMapping("/main")
	public String main(Model model, HttpServletRequest request,
			HttpServletResponse response) {
		
				
		MainModelCreator modelCreator = new MainModelCreator();
		MainModel mainModel = (MainModel) modelCreator.createModel(request);			
		 
		if (request.getParameter("button") != null && 
				request.getParameter("button").equals("login")) {
			
			if (mainModel.getUserLogin() != null
					&& mainModel.getUserLogin().isEmpty()) {
				mainModel.setErrorMessage("Login empty!");
			} else if (mainModel.getUserPassword() != null
					&& mainModel.getUserPassword().isEmpty()) {
				mainModel.setErrorMessage("Password Empty!");
			} else {
				
				User user = userDao.getUser(mainModel.getUserLogin(), mainModel.getUserPassword());
				if (user == null) {
					log.debug("User not found " + mainModel.getUserLogin());
					//user not found
					mainModel.setErrorMessage("Cannot find user [" + mainModel.getUserLogin() + "]");
				} else {
					log.debug("User found " + mainModel.getUserLogin());
					// set user to the session
					request.getSession().setAttribute("currentUserId", user.getId());
					mainModel.setCurrentUserId(user.getId());
				}			
			}
						
		}	
		
				
		mainModel.setRooms(getActiveRooms());
		mainModel.setMessages(getFormattedMessages(mainModel));
		mainModel.setUsersOnline(getUsersOnline(mainModel));
		mainModel.setCurrentRoom(getCurrentRoom(mainModel.getCurrentRoomId()));
		mainModel.setCurrentUser(getCurrentUser(mainModel.getCurrentUserId()));
			
		// create model here
		model.addAttribute("model", mainModel);
		log.debug("main action -> view");		
		return "Main";
	}

	private User getCurrentUser(Integer currentUserId) {
		
		User user = null;
		if (currentUserId != null) {
			user = userDao.getUser(currentUserId);

		}
				
		return user;
	}

	private Room getCurrentRoom(Integer currentRoomId) {

		Room room = null;
		if (currentRoomId != null) {
			room = roomDao.SelectRoom(currentRoomId);

		}
				
		return room;
	}

	private List<String> getUsersOnline(MainModel mainModel) {

		List<String> chatUsers = new ArrayList<String>();

		Map<Integer, Integer> usersOnline = UsersOnlineHttpSessionAttributeListener
								.getActiveUsers();
		
		log.debug("getUsersOnline : " + usersOnline.toString());
		
		Integer currentRoomId = mainModel.getCurrentRoomId();
		for (Integer user_id : usersOnline.keySet()) {

			if (currentRoomId.equals(usersOnline.get(user_id))) {

				User user = userDao.getUser(user_id);
				if (user != null)
					chatUsers.add(user.getUserNickName());
			}
		}

		log.debug("chat users : " + Arrays.toString(chatUsers.toArray()));
		return chatUsers;
	}

	private List<String> getFormattedMessages(MainModel mainModel) {

		List<String> messages = new ArrayList<String>();

		if (mainModel.getCurrentRoomId() != null) {
			Room room = roomDao.SelectRoom(mainModel.getCurrentRoomId());

			SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
			for (Message msgObj : room.getMessages()) {
				
				String message = String.format("[%1s] %2s : %3s", 
						sdf.format(msgObj.getCreateDate()), 
						msgObj.getUser().getUserNickName(),
						msgObj.getMsg());
				messages.add(message);
			}

		}

		log.debug("getMessages : " + Arrays.toString(messages.toArray()));

		return messages;
	}

	private List<Room> getActiveRooms() {

		List<Room> activeRooms = roomDao.SelectRooms();

		log.debug("getActiveRooms : " + Arrays.toString(activeRooms.toArray()));
		return activeRooms;
	}

}
